﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
using System.Management;
using System.Collections;
// namespaces necesarios para conexión a bd
using System.Data;
using System.Data.Common;
using System.Data.SqlClient;
using System.Data.SqlTypes;

using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;

namespace Persistencia_y_capa_de_negocio
{
    /// <summary>
    /// CADEdificioUsuario. Componente de acceso a la base de datos UsuariosEdificio.
    /// </summary>
    public class CADEdificioUsuario
    {
        /// <summary>
        /// Representa una instancia de la clase.De forma que no he de crear
        /// una nueva cada vez.
        /// </summary>
        private static readonly CADEdificioUsuario instancia = new CADEdificioUsuario();
        /// <summary>
        /// Me permite obtener la variable privada instancia de la clase
        /// De esta forma siempre uso el mismo objeto que representa la clase.
        /// </summary>
        public static CADEdificioUsuario Instancia
        {
            get { return instancia; }
        }
        /// <summary>
        /// Variable para almacenar la cadena de conexión
        /// </summary>
        private string cadCon;
        private SqlDataAdapter da;
        private SqlConnection c;
        private DataSet vdb;

        /// <summary>
        /// Constructor por defecto de la clase CADEdificioUsuario
        /// </summary>
        public CADEdificioUsuario()
        {
            try
            {
                cadCon = ConfigurationManager.ConnectionStrings["conexion"].ConnectionString;

                c = new SqlConnection(cadCon);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }



        }

        /// <summary>
        /// Permite obtener la lista de edificios de un determinado usuario
        /// </summary>
        /// <param name="idUs">Id del usuario</param>
        /// <returns> Lista de objetos ENEdificioUsuario que contienen los edificios del usuario</returns>
        public ArrayList obtenerEdificiosUsuario(int idUs)
        {
            vdb = new DataSet();//Tengo que declarar aqui el DataSet porque sino utiliza el mismo siempre.
            //y por eso me fallaba
            da = new SqlDataAdapter("Select * from UsuariosEdificio where " + idUs.ToString() +
                                        "=usuario order by edificio asc", c);
            da.Fill(vdb, "EdificiosUsuario");
            ArrayList lista = new ArrayList();
            DataTable tabla = new DataTable();
            tabla = vdb.Tables["EdificiosUsuario"];

            foreach (DataRow fila in tabla.Rows)
            {
                EnEdificioUsuario edus = new EnEdificioUsuario();
                edus.IDEdificio = Convert.ToInt32(fila["edificio"]);
                edus.IDUsuario = Convert.ToInt32(fila["usuario"]);
                edus.NivelEd = Convert.ToInt32(fila["nivel"]);

                lista.Add(edus);
            }
            return lista;
        }

        public EnEdificioUsuario obtenerEdificioUsuario(int idUs, int idEd)
        {
            DataTable t = vdb.Tables["EdificiosUsuario"];
            EnEdificioUsuario edu = new EnEdificioUsuario();

            string select = "usuario = \'" + idUs.ToString() + " \' and edificio = \' " + idEd.ToString() + " \'";

            try
            {
                DataRow r = t.Select(select)[0];
                edu.IDEdificio = Convert.ToInt32(r["edificio"]);
                edu.IDUsuario = Convert.ToInt32(r["usuario"]);
                edu.NivelEd = Convert.ToInt32(r["nivel"]);

            }
            catch
            {
            }

            return edu;
        }

        /// <summary>
        /// Permite dar de baja todos los edificios de un determinado usuario.
        /// </summary>
        /// <param name="iduser"> ID del usuario </param>
        public void DarDeBajaTodosEdificiosUsuario(int iduser)
        {
            string select;
            DataTable tabla = vdb.Tables["EdificiosUsuario"];
            DataRow[] filasEncontradas;

            select = "usuario = \'" + iduser.ToString() + "\'";

            try
            {
                //Obtengo una matriz de filas, con las fila en las que el campo coincide
                filasEncontradas = tabla.Select(select);
                //Recorro las filas encontradas y las voy borrando desde la ultima a la primera.
                for (int i = (filasEncontradas.Length - 1); i >= 0; i--)
                {
                    filasEncontradas[i].Delete();
                }
                SqlCommandBuilder command = new SqlCommandBuilder(da);
                da.Update(vdb, "EdificiosUsuario");
            }
            catch (Exception)
            {

                //No hay que hacer nada.
            }
        }

        /// <summary>
        /// Permite dar de baja una lista de edificios.
        /// </summary>
        /// <param name="listaid">Lista de objetos EnEdificioUsuario que contienen los edificios</param>
        public void DarDeBajaEdificiosUsuario(ArrayList listaid)
        {
            string select = "";
            DataTable tabla = vdb.Tables["EdificiosUsuario"];
            foreach (EnEdificioUsuario idus in listaid)
            {
                select = "usuario = \'" + idus.IDUsuario.ToString() + "\' AND edificio = \'" + idus.IDEdificio.ToString() + "\'";
                try
                {
                    DataRow fila = tabla.Select(select)[0];
                    fila.Delete();
                }
                catch (Exception)
                {

                    //No hay que hacer nada.
                }
            }
                SqlCommandBuilder command = new SqlCommandBuilder(da);
                da.Update(vdb, "EdificiosUsuario");
        }

        /// <summary>
        /// Parmite dar de alta una lista de edificios.
        /// </summary>
        /// <param name="listaid">Lista de objetos EnEdificioUsuario que contienen los edificios</param>
        public void DarDeAltaEdificiosUsuario(ArrayList listaid)
        {
            string select;
            DataTable tabla = vdb.Tables["EdificiosUsuario"];
            foreach (EnEdificioUsuario idus in listaid)
            {
                //Esta select la usare para comprobar si ya esta dado de alta ese edificio con ese usuario.
                select = "usuario = \'" + idus.IDUsuario.ToString() + "\' AND edificio = \'" + idus.IDEdificio.ToString() + "\'";
                try
                {
                    DataRow fila = tabla.Select(select)[0];
                }
                catch (Exception)
                {
                        //Tengo que añadirlo pues no esta.
                        DataRow fila = tabla.NewRow();
                        fila["usuario"] = idus.IDUsuario;
                        fila["edificio"] = idus.IDEdificio;
                        fila["nivel"] = idus.NivelEd;

                        tabla.Rows.Add(fila);
                }

            }

            SqlCommandBuilder command = new SqlCommandBuilder(da);

            da.Update(vdb, "EdificiosUsuario");


        }

        /// <summary>
        /// Método que mejora en un nivel, el edificio del usuario nombrado;
        /// </summary>
        /// <param name="idUsuario">Usuario del que queremos mejorar el edificio.</param>
        /// <param name="idEdificio">Edificio que queremos mejorar.</param>
        public void MejoraEdificioUsuario(int idUsuario, int idEdificio)
        {
            ArrayList lista = obtenerEdificiosUsuario(idUsuario);
            ArrayList listaAuxiliar = new ArrayList();
            bool anadido = false;

            if (lista.Count == 0)
            {
                // El usuario no tenía ningún edificio anteriormente y tenemos que crearlo a mano.
                EnEdificioUsuario edu = new EnEdificioUsuario();

                edu.IDEdificio = idEdificio;
                edu.IDUsuario = idUsuario;
                edu.NivelEd = 1;            // El nivel es 1 ya que no había hasta ahora.

                listaAuxiliar.Clear();
                listaAuxiliar.Add(edu);

                DarDeAltaEdificiosUsuario(listaAuxiliar);

                anadido = true;
            }
            else
            {
                // Sí que había unidades y vamos a buscar las del tipo indicado por la función
                foreach (EnEdificioUsuario enu in lista)
                {
                    if (enu.IDEdificio == idEdificio)
                    {
                        enu.NivelEd += 1;

                        listaAuxiliar.Clear();
                        listaAuxiliar.Add(enu);

                        // Primero eliminamos el edificio de la lista:
                        DarDeBajaEdificiosUsuario(listaAuxiliar);

                        listaAuxiliar.Clear();
                        listaAuxiliar.Add(enu);

                        // Y ahora volvemos a insertar el edificio con los datos actualizados.
                        DarDeAltaEdificiosUsuario(listaAuxiliar);

                        anadido = true;
                    }
                }

                if (anadido == false)
                {
                    // El usuario no tenía ningún edificio de este tipo anteriormente y tenemos que crearlo manualmente
                    EnEdificioUsuario edu = new EnEdificioUsuario();

                    edu.IDEdificio = idEdificio;
                    edu.IDUsuario = idUsuario;
                    edu.NivelEd = 1;            // El nivel es 1 ya que no había hasta ahora.

                    listaAuxiliar.Clear();
                    listaAuxiliar.Add(edu);

                    DarDeAltaEdificiosUsuario(listaAuxiliar);

                    anadido = true;
                }
            }
        }

    }
}
